using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace LuaWinCE
{
    class Lua
    {
        public const string DLL = @"\storage card\luacedll.dll";
        
        // typedef int (*lua_CFunction) (lua_State *L);
        public delegate int lua_CFunction (IntPtr L);

        public const int LUA_TNONE          = -1;
        public const int LUA_TNIL           = 0;
        public const int LUA_TBOOLEAN       = 1;
        public const int LUA_TLIGHTUSERDATA = 2;
        public const int LUA_TNUMBER        = 3;
        public const int LUA_TSTRING        = 4;
        public const int LUA_TTABLE         = 5;
        public const int LUA_TFUNCTION      = 6;
        public const int LUA_TUSERDATA      = 7;
        public const int LUA_TTHREAD        = 8;
        public const int LUA_NUMTAGS        = 9;

        [DllImport(DLL)]
        public static extern int lua_type (IntPtr L, int n);

        //#define lua_isnoneornil(L,n) (lua_type(L, (n)) <= 0)
        public static bool lua_isnoneornil(IntPtr L, int n)
        {
            return LUA_TNONE == lua_type(L, n) ||
                    LUA_TNIL == lua_type(L, n);
        }
        
        //#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE)
        public static bool lua_isnone(IntPtr L, int n)
        {
            return LUA_TNONE == lua_type(L, n);
        }

        //#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL)
        public static bool lua_isnil(IntPtr L, int n)
        {
            return LUA_TNIL == lua_type(L, n);
        }

        //#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN)
        public static bool lua_isboolean(IntPtr L, int n)
        {
            return LUA_TBOOLEAN == lua_type(L, n);
        }

        //#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA)
        public static bool lua_islightuserdata(IntPtr L, int n)
        {
            return LUA_TLIGHTUSERDATA == lua_type(L, n);
        }

        //public const int LUA_TNUMBER = 3;
        [DllImport(DLL)]
        public static extern int lua_isnumber (IntPtr L, int n);
        public static bool lua_isnumberb (IntPtr L, int n)
        {
            return 0 != lua_isnumber(L, n);
        }

        //public const int LUA_TSTRING = 4;
        [DllImport(DLL)]
        public static extern int lua_isstring (IntPtr L, int n);
        public static bool lua_isstringb(IntPtr L, int n)
        {
            return 0 != lua_isstring(L, n);
        }

        //#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE)
        public static bool lua_istable(IntPtr L, int n)
        {
            return LUA_TTABLE == lua_type(L, n);
        }

        //#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION)
        public static bool lua_isfunction (IntPtr L, int n)
        {
            return LUA_TFUNCTION == lua_type(L, n);
        }

        //public const int LUA_TUSERDATA = 7;
        [DllImport(DLL)]
        public static extern int lua_isuserdata (IntPtr L, int n);

        //#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD)
        public static bool lua_isthread (IntPtr L, int n)
        {
            return LUA_TTHREAD == lua_type(L, n);
        }

        //public const int LUA_NUMTAGS = 9;
        // ???

        [DllImport(DLL)]
        public static extern void lua_pushboolean(IntPtr L, int boolean);

        [DllImport(DLL)]
        public static extern void lua_pushnumber (IntPtr L, double number);
        
        [DllImport(DLL)]
        public static extern void lua_pushinteger (IntPtr L, long integer);

        [DllImport(DLL)]
        public static extern void lua_pushstring (IntPtr L, string @string);

        [DllImport(DLL)]
        public static extern IntPtr luaL_newstate ();

        [DllImport(DLL)]
        public static extern void luaL_openlibs (IntPtr L);

        [DllImport(DLL)]
        public static extern int luaL_loadstring (IntPtr L, string s);

        [DllImport(DLL)]
        public static extern int lua_pcallk (IntPtr L, int nargs, int nresults, int errfunc, int ctx, lua_CFunction f);

        //#define lua_pcall(L,n,r,f)	lua_pcallk(L, (n), (r), (f), 0, NULL)
        public static int lua_pcall (IntPtr L, int nargs, int nresults, int errfunc)
        {
            return lua_pcallk (L, nargs, nresults, errfunc, 0, null);
        }

        [DllImport(DLL)]
        public static extern void lua_getglobal (IntPtr L, string var);

        [DllImport(DLL)]
        public static extern double lua_tonumberx (IntPtr L, int n, ref int isNumber);
        
        //#define lua_tonumber(L,i)	lua_tonumberx(L,i,NULL)
        public static double lua_tonumber (IntPtr L, int n)
        {
            int isNumber = 0;
            lua_tonumberx(L, n, ref isNumber);
            return lua_tonumberx (L, n, ref isNumber);
        }

        [DllImport(DLL)]
        public static extern void lua_settop (IntPtr L, int idx);
        
        //#define lua_pop(L,n) lua_settop(L, -(n)-1)
        public static void lua_pop (IntPtr L, int cantidad)
        {
            lua_settop (L, - cantidad - 1);
        }

        [DllImport(DLL)]
        public static extern void lua_close (IntPtr L);

        [DllImport(DLL)]
        public static extern string lua_tolstring(IntPtr L, int idx, UIntPtr len);

        public static string lua_tostring(IntPtr L, int idx)
        {
            return lua_tolstring (L, idx, UIntPtr.Zero);
        }

        //LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {
        [DllImport(DLL)]
        public static extern void lua_pushcclosure (IntPtr L, lua_CFunction fn, int n);

        public static void lua_pushcfunction (IntPtr L, lua_CFunction fn)
        {
            lua_pushcclosure (L, fn, 0);
        }

        //LUA_API void lua_setglobal (lua_State *L, const char *var) {
        [DllImport(DLL)]
        public static extern void lua_setglobal (IntPtr L, string var);

    }
}
